Skip to content

fix: reject transport headers as model-rewrite promotion targets - #974

Open
mkoushni wants to merge 11 commits into
praxis-proxy:mainfrom
mkoushni:fix/554-model-rewrite-promotion-headers
Open

fix: reject transport headers as model-rewrite promotion targets#974
mkoushni wants to merge 11 commits into
praxis-proxy:mainfrom
mkoushni:fix/554-model-rewrite-promotion-headers

Conversation

@mkoushni

@mkoushni mkoushni commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

openai_responses_model_rewrite previously accepted any syntactically valid HTTP header name for headers.effective_model and headers.original_model. That allowed configs such as effective_model: content-length to promote a client-derived model string onto hop-by-hop, framing, Host, or proxy-auth headers.

  • Reject those transport-controlled names at config load, case-insensitively.
  • Reject using the same promotion header for both original and effective model values.
  • Share the blocked-name check with API-client forward_headers validation via is_transport_controlled_header.

Default x-praxis-ai-* promotion headers are unchanged.

Related issue

Closes #554

Validation

  • Unit tests
  • Integration or functional tests
  • make lint

Covered by openai_responses_model_rewrite and promotion unit tests. make coverage-check passed at 96.06% line coverage. cargo clippy -p praxis-ai-apis --all-targets -- -D warnings passed. No new example config is required; existing defaults remain valid.

Checklist

  • I reviewed every changed line and can explain the change.
  • User-facing behavior and generated documentation are updated.
  • Commits are signed and include a Signed-off-by trailer.

Breaking changes

Configs that named a hop-by-hop, framing, Host, or proxy-auth header as a model-rewrite promotion target, or that used the same header for both promoted values, now fail at filter construction.

…xis-proxy#554)

Configurable effective/original model headers could previously name
Content-Length, Host, or hop-by-hop headers and conflict with framing.
Share the blocked-name check with API-client forward-header validation
and reject duplicate promotion names.

Signed-off-by: mkoushni <mkoushni@redhat.com>
@mkoushni
mkoushni requested review from a team and aslakknutsen September 7, 2026 13:54
The postgres vLLM job co-locates Postgres, vLLM, and OGX; the shipped
chat file-search example still uses a 60s IRR step and 5s callout, so a
slow CPU inference can 504 before the 300s OpenAI client timeout.
Match the native file-search template deadlines in the CI-only patcher.

Signed-off-by: mkoushni <mkoushni@redhat.com>
Compose the promotion-header denylist on http_hop plus Host and
Content-Length after outbound hop-by-hop sanitization landed on main.

Signed-off-by: mkoushni <mkoushni@redhat.com>

@leseb leseb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: promotion.rs:29 still permits authorization and unrelated internal x-praxis-* targets. A client model such as Bearer attacker can overwrite upstream credentials or routing facts.
P1: The class-level fix is missing from Anthropic config:122 and Responses-format config:112, which retain syntax-only validation before promoting body-derived values. Issue #554 explicitly requires these sibling sinks to be fixed.
P2: Generated documentation:17 omits the new requirement that original/effective header names must differ.

…-promotion-headers

Signed-off-by: mkoushni <mkoushni@redhat.com>
Block Authorization and x-praxis-* names outside the AI fact namespaces
so a client model cannot overwrite credentials or routing. Apply the same
validator to Responses and Anthropic format classifiers, and document
that original/effective rewrite headers must differ.

Signed-off-by: mkoushni <mkoushni@redhat.com>
@mkoushni

mkoushni commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

> P1: promotion.rs:29 still permits authorization and unrelated internal x-praxis-* targets. A client model such as Bearer attacker can overwrite upstream credentials or routing facts. P1: The class-level fix is missing from Anthropic config:122 and Responses-format config:112, which retain syntax-only validation before promoting body-derived values. Issue #554 explicitly requires these sibling sinks to be fixed. P2: Generated documentation:17 omits the new requirement that original/effective header names must differ.

P1 credentials / internal headers. Promotion targets now reject authorization/cookie/set-cookie/www-authenticate and x-praxis-* names outside the AI fact namespaces (x-praxis-ai-, x-praxis-responses-). Defaults such as x-praxis-ai-effective-model and x-praxis-responses-mode stay allowed. forward_headers still uses only the transport list, so Authorization can still be forwarded to APIs.

P1 sibling sinks. openai_responses_format and anthropic_messages_format use the same validate_promotion_header helper.

P2 docs. Generated model-rewrite docs now say effective_model and original_model must use distinct names.

CI clippy -D unwrap_used failed on unwrap_err in the new authorization
rejection test. Match the crate's existing test-module suppressions.

Signed-off-by: mkoushni <mkoushni@redhat.com>
…-promotion-headers

Signed-off-by: mkoushni <mkoushni@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configurable AI promotion headers can target transport and credential headers

2 participants